// 解析虚拟节点创建真实dom
export function patch(oldVNode, vNode) {
	// 如果原来的没有值,表示是组件的挂载
	if (!oldVNode) {
		console.log(vNode)
		// 通过当前的虚拟节点创建真实dom节点并且返回
		return createEl(vNode);
	} else {
		// 判断oldVNode是不是真实dom
		const isRealElement = oldVNode.nodeType; // 如果有nodeType属性就是真实dom
		if (isRealElement) {
			const oldEl = oldVNode; // 当前的真实dom <div id="app"></div>
			// 拿到当前的真实dom的父元素
			const parentEl = oldEl.parentNode; // body
			// 通过虚拟dom创建真实dom
			const el = createEl(vNode);
			// 在当前真实dom前插入创建好的dom
			parentEl.insertBefore(el, oldEl.nextSibling);
			// 移除掉老的真实dom
			parentEl.removeChild(oldEl);
			// 返回真实dom
			return el;
		}
	}
}

// 根据组件虚拟节点创建真实dom节点
function createComponent(vNode) {
	let i = vNode.data;
	// 判断有没有hook,hook里有没有init方法
	if ((i = i.hook) && (i = i.init)) {
		// 调用组件内部的init方法
		i(vNode);
	}
	// 如果节点上有组件实例说明是组件
	if (vNode.componentsInstance) {
		return true;
	} else {
		return false;
	}
}

// 通过虚拟节点创建真实dom元素
function createEl(vNode) {
	const { tag, children, text } = vNode;
	// 判断是标签还是文本
	if (typeof tag === "string") {
		// 判断是不是自定义组件
		if (createComponent(vNode)) {
			// 返回组件的挂载点
			return vNode.componentsInstance.$el;
		}
		vNode.el = document.createElement(tag);
		// 更新元素属性
		updateProperties(vNode);
		// 遍历递归创建子元素,并且将当前元素添加上创建的子元素
		children.forEach((child) => vNode.el.appendChild(createEl(child)));
	} else {
		// 虚拟dom上映射着真实dom,方便后续进行diff
		vNode.el = document.createTextNode(text);
	}
	// 返回当前创建的真实dom
	return vNode.el;
}

// 更新元素属性
function updateProperties(vNode) {
	// 获取当前的真实dom
	const el = vNode.el;
	// 获取属性
	const props = vNode.data;
	// 遍历属性
	for (const key in props) {
		// 根据key不同来分别操作
		if (key === "style") {
			// 设置样式
			for (const name in props.style) {
				el.style[name] = props.style[name];
			}
		} else {
			el.setAttribute(key, props[key]);
		}
	}
}
